package ch.zbw.pra.sysventory.presentation.panels;

import java.io.Serializable;
import java.util.List;

import ch.zbw.pra.sysventory.application.controller.ScanversionArchivePanelController;
import ch.zbw.pra.sysventory.model.Computer;
import ch.zbw.pra.sysventory.model.HardDisk;
import ch.zbw.pra.sysventory.model.Nic;
import ch.zbw.pra.sysventory.model.OperatingSystem;
import ch.zbw.pra.sysventory.model.Printer;
import ch.zbw.pra.sysventory.model.Processor;
import ch.zbw.pra.sysventory.model.Scanversion;
import ch.zbw.pra.sysventory.model.Software;
import ch.zbw.pra.sysventory.utils.DateUtils;

import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.util.HierarchicalContainer;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.event.ItemClickEvent.ItemClickListener;
import com.vaadin.terminal.Sizeable;
import com.vaadin.terminal.ThemeResource;
import com.vaadin.ui.AbstractSelect;
import com.vaadin.ui.HorizontalSplitPanel;
import com.vaadin.ui.Table;
import com.vaadin.ui.Tree;
import com.vaadin.ui.VerticalLayout;

/**
 * Painted das ScanversionArchivePanel
 * 
 * @author Ralph Koster
 */

public class ScanversionArchivePanel extends VerticalLayout implements
		Property.ValueChangeListener, Serializable {

	private static final long serialVersionUID = 4815511618648432891L;
	private ScanversionArchivePanelController scanversionArchivePanelController;

	private HorizontalSplitPanel splitPanel;
	private VerticalLayout leftLayout;
	private VerticalLayout rightLayout;
	private Table scanversionsTable;
	private Tree scanversionTree;
	private IndexedContainer indexedContainer;
	private HierarchicalContainer container;
	private Item item;
	private int itemId;
	private int parentItemId;

	public ScanversionArchivePanel() {
		this.scanversionArchivePanelController = new ScanversionArchivePanelController();
		this.setCaption("Scanversionen");
		this.setStyleName("scanversionsArchivePanel");
		this.setWidth(100, Sizeable.UNITS_PERCENTAGE);
		this.setHeight(100, Sizeable.UNITS_PERCENTAGE);

		splitPanel = new HorizontalSplitPanel();
		leftLayout = new VerticalLayout();
		rightLayout = new VerticalLayout();
		scanversionTree = new Tree();

		splitPanel.setWidth(100, Sizeable.UNITS_PERCENTAGE);
		splitPanel.setHeight(100, Sizeable.UNITS_PERCENTAGE);

		paintLeftLayout();

		splitPanel.setSplitPosition(47, Sizeable.UNITS_PERCENTAGE);
		splitPanel.setFirstComponent(leftLayout);
		splitPanel.setSecondComponent(rightLayout);

		this.addComponent(splitPanel);
	}

	private void paintLeftLayout() {
		leftLayout.removeAllComponents();
		leftLayout.setSizeFull();

		scanversionsTable = new Table("Scanversionen:");

		indexedContainer = new IndexedContainer();
		indexedContainer = loadScanversions();

		scanversionsTable.setSizeUndefined();
		scanversionsTable.setHeight(97, Sizeable.UNITS_PERCENTAGE);

		scanversionsTable.setSelectable(true);
		scanversionsTable.setImmediate(true);
		scanversionsTable.setRowHeaderMode(Table.ROW_HEADER_MODE_INDEX);
		scanversionsTable.setColumnCollapsingAllowed(true);
		scanversionsTable.setColumnReorderingAllowed(true);
		scanversionsTable.setStyleName("table");
		scanversionsTable.setContainerDataSource(indexedContainer);
		scanversionsTable.setVisibleColumns(new String[] {
				"Scanversion Nummer", "Scanversion gestartet",
				"Scanversion beendet" });
		scanversionsTable.setSelectable(true);
		scanversionsTable.setImmediate(true);
		scanversionsTable.addListener(this);

		leftLayout.addComponent(scanversionsTable);
	}

	private void paintScanversionTree(String scanversionId) {
		rightLayout.removeAllComponents();
		rightLayout.setSizeFull();
		Scanversion scanversion = scanversionArchivePanelController
				.getScanversionById(scanversionId);

		scanversionTree = new Tree();
		scanversionTree.removeAllItems();

		paintScanversionContainer(scanversion);

		scanversionTree.setStyleName("scanversionTree");
		scanversionTree.setSizeFull();
		scanversionTree
				.setCaption("Gescannte Komponente in der selektierten Scanversion:");
		scanversionTree.setContainerDataSource(container);
		scanversionTree.setItemCaptionPropertyId("name");
		scanversionTree
				.setItemCaptionMode(AbstractSelect.ITEM_CAPTION_MODE_PROPERTY);
		scanversionTree.setSelectable(false);
		scanversionTree.setImmediate(true);
		scanversionTree.addListener(new ItemClickListener() {

			/**
			 * 
			 */
			private static final long serialVersionUID = 4249426231545952109L;

			@Override
			public void itemClick(ItemClickEvent event) {
				Object itemId = event.getItemId();
				if (!scanversionTree.isExpanded(itemId)
						&& scanversionTree.hasChildren(itemId)) {
					scanversionTree.expandItem(itemId);
				} else {
					scanversionTree.collapseItem(itemId);
				}
			}
		});
		rightLayout.addComponent(scanversionTree);
	}

	private void paintScanversionContainer(Scanversion scanversion) {
		item = null;
		itemId = 0;

		container = new HierarchicalContainer();
		container.addContainerProperty("name", String.class, null);
		container.addContainerProperty("icon", ThemeResource.class,
				new ThemeResource("../runo/icons/16/document.png"));

		addComputersToTree(scanversion);
	}

	private void addComputersToTree(Scanversion scanversion) {
		List<Computer> computers = scanversion.getComputers();
		for (Computer computer : computers) {
			String parent = "Hostname: " + computer.getHostNameComputer();
			String computerRam = "RAM: " + computer.getRamComputer();
			String computerSid = "Sid: " + computer.getSidComputer();
			String computerType = "Typ: " + computer.getTypeComputer();

			// Add the parent to the tree
			item = container.addItem(itemId);
			item.getItemProperty("name").setValue(parent);
			container.setChildrenAllowed(itemId, true);
			parentItemId = itemId;
			itemId++;

			String[] leafValues = new String[] { computerRam, computerSid,
					computerType };

			addLeafsToChildren(leafValues, parentItemId);

			addOperatingSystemToComputer(computer);
			addProcessorToComputer(computer);
			addHardDisksToComputer(computer);
			addPrintersToComputer(computer);
			addNicsToComputer(computer);
			addSoftwareToComputer(computer);
		}
	}

	private void addOperatingSystemToComputer(Computer computer) {
		OperatingSystem operatingSystem = computer.getOs();

		String bsParent = "Betriebssystem";

		int bsParentItemId = addObjectParent(bsParent);

		String osName = "Name: " + operatingSystem.getNameOperatingSystem();
		String osVersion = "Version: "
				+ operatingSystem.getBuildOperatingSystem();
		String osArchitecture = "Architektur: "
				+ operatingSystem.getArchitecture32Bit64BitOperatingSystem();

		String[] childrenValues = new String[] { osName, osVersion,
				osArchitecture };

		addLeafsToChildren(childrenValues, bsParentItemId);
	}

	private void addProcessorToComputer(Computer computer) {
		Processor processor = computer.getProcessor();

		String procParent = "Prozessor";

		int procParentItemId = addObjectParent(procParent);

		String processorName = "Name: " + processor.getNameProcessor();
		String processorFamily = "Familie: " + processor.getFamilyProcessor();
		String processorCores = "Kerne: " + processor.getCoresProcessor();
		String processorClock = "Taktrate: " + processor.getClockProcessor();

		String[] childrenValues = new String[] { processorName,
				processorFamily, processorCores, processorClock };

		addLeafsToChildren(childrenValues, procParentItemId);
	}

	private void addHardDisksToComputer(Computer computer) {
		List<HardDisk> hardDisks = computer.getHardDisks();

		String hardDiskParent = "Festplatten";

		int hardDiskParentItemId = addObjectParent(hardDiskParent);

		for (HardDisk hardDisk : hardDisks) {
			String hardDiskDriveLetter = "Name: " + hardDisk.getDriveLetter();
			String hardDiskCapacity = "Grösse: "
					+ hardDisk.getHardDiskCapacity();
			String hardDiskFreeSpace = "Freier Speicher: "
					+ hardDisk.getHardDiskFreeSpace();
			String hardDiskEfficiency = "Auslastung: "
					+ hardDisk.getHardDiskEfficiency();

			String[] leafValues = new String[] { hardDiskCapacity,
					hardDiskFreeSpace, hardDiskEfficiency };

			int childrenItemId = addChildrenToParent(hardDiskDriveLetter,
					hardDiskParentItemId);
			addLeafsToChildren(leafValues, childrenItemId);
		}
	}

	private void addPrintersToComputer(Computer computer) {
		List<Printer> printers = computer.getPrinters();

		String printerParent = "Drucker";

		int printerParentItemId = addObjectParent(printerParent);

		for (Printer printer : printers) {
			String printerName = "Name: " + printer.getNamePrinter();
			String printerDriverName = "Treiber: "
					+ printer.getDriverNamePrinter();
			String printerDriverVersion = "Treiber Version: "
					+ printer.getDriverVersionPrinter();

			String[] leafValues = new String[] { printerDriverName,
					printerDriverVersion };

			int childrenItemId = addChildrenToParent(printerName,
					printerParentItemId);
			addLeafsToChildren(leafValues, childrenItemId);
		}
	}

	private void addNicsToComputer(Computer computer) {
		List<Nic> nics = computer.getNics();

		String nicParent = "NIC";

		int nicParentItemId = addObjectParent(nicParent);

		for (Nic nic : nics) {
			String nicName = "Name: " + nic.getNameNic();
			String nicIPv4 = "IPv4: " + nic.getIpv4Nic();
			String nicIPv6 = "IPv6: " + nic.getIpv6Nic();
			String subnet = "Subnetz: " + nic.getSubnetNic();
			String macAddress = "MAC Adresse: " + nic.getMacAdressNic();
			String dhcp = "DHCP: " + nic.getDhcpNic();
			String standardGateway = "Standard Gateway: "
					+ nic.getStandardGatewayNic();

			String[] leafValues = new String[] { nicIPv4, nicIPv6, subnet,
					macAddress, dhcp, standardGateway };

			int childrenItemId = addChildrenToParent(nicName, nicParentItemId);

			addLeafsToChildren(leafValues, childrenItemId);
		}
	}

	private void addSoftwareToComputer(Computer computer) {
		List<Software> softwares = computer.getSoftwares();

		String softwareParent = "Software";

		int softwareParentItemId = addObjectParent(softwareParent);

		for (Software software : softwares) {
			String softwareName = "Name: " + software.getNameSoftware();
			String softwareVersion = "Version: "
					+ software.getVersionSoftware();
			String softwareVendor = "Hersteller: "
					+ software.getSoftwareVendor();

			String[] leafValues = new String[] { softwareVersion,
					softwareVendor };

			int childrenItemId = addChildrenToParent(softwareName,
					softwareParentItemId);

			addLeafsToChildren(leafValues, childrenItemId);
		}
	}

	private int addObjectParent(String parentValue) {
		item = container.addItem(itemId);
		item.getItemProperty("name").setValue(parentValue);
		container.setParent(itemId, parentItemId);
		container.setChildrenAllowed(itemId, true);
		int objectParentItemId = itemId;
		itemId++;
		return objectParentItemId;
	}

	private int addChildrenToParent(String value, int parentItemId) {
		item = container.addItem(itemId);
		item.getItemProperty("name").setValue(value);
		container.setParent(itemId, parentItemId);
		container.setChildrenAllowed(itemId, true);
		int childrenItemId = itemId;
		itemId++;
		return childrenItemId;
	}

	private void addLeafsToChildren(String[] leafValues, int parentItemId) {
		for (String value : leafValues) {
			item = container.addItem(itemId);
			item.getItemProperty("name").setValue(value);
			container.setParent(itemId, parentItemId);
			container.setChildrenAllowed(itemId, false);
			itemId++;
		}
	}

	private IndexedContainer loadScanversions() {
		IndexedContainer indexedContainer = new IndexedContainer();
		indexedContainer.addContainerProperty("Scanversion Id", String.class,
				null);
		indexedContainer.addContainerProperty("Scanversion Nummer",
				String.class, null);
		indexedContainer.addContainerProperty("Scanversion gestartet",
				String.class, null);
		indexedContainer.addContainerProperty("Scanversion beendet",
				String.class, null);
		List<Scanversion> scanversions = scanversionArchivePanelController
				.loadScanversions();
		for (Scanversion scanversion : scanversions) {
			int scanversionId = scanversion.getId();
			long scanversionNumber = scanversion.getNumberOfScanversion();
			String scanversionStart = DateUtils
					.convertTimestampToDateTime(scanversion
							.getScanStartTimestamp());
			String scanversionEnd = DateUtils
					.convertTimestampToDateTime(scanversion
							.getScanEndeTimestamp());
			Object id = indexedContainer.addItem();
			indexedContainer.getContainerProperty(id, "Scanversion Id")
					.setValue(scanversionId);
			indexedContainer.getContainerProperty(id, "Scanversion Nummer")
					.setValue(scanversionNumber);
			indexedContainer.getContainerProperty(id, "Scanversion gestartet")
					.setValue(scanversionStart);
			indexedContainer.getContainerProperty(id, "Scanversion beendet")
					.setValue(scanversionEnd);
		}
		return indexedContainer;
	}

	@Override
	public void valueChange(ValueChangeEvent event) {
		if (event.getProperty().getValue() != null) {
			String scanversionId = String.valueOf(scanversionsTable.getItem(
					event.getProperty().getValue()).getItemProperty(
					"Scanversion Id"));
			paintScanversionTree(scanversionId);
		}
	}

	public void updateScanversionArchivePanel() {
		paintLeftLayout();
	}
}
